﻿<!--
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
-->

<UserControl x:Class="System.Windows.Controls.Samples.UpDownBaseSample"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    
    xmlns:samples="clr-namespace:System.Windows.Controls.Samples">
    <StackPanel>
        <!-- UpDownBase&lt;T&gt; -->
        <ContentControl Content="UpDownBase&lt;T&gt;" Style="{StaticResource Header}" />
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="50" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="200" />
                <ColumnDefinition Width="200" />
                <ColumnDefinition Width="200" />
            </Grid.ColumnDefinitions>

            <TextBlock Grid.Row="0" Grid.Column="0" Style="{StaticResource Description}" Text="NUD : UpDownBase&lt;int&gt;"/>
            <StackPanel x:Name="spNUD" Grid.Row="1" Grid.Column="0" Margin="5"/>
            <TextBlock Grid.Row="0" Grid.Column="1" Style="{StaticResource Description}" Text="TUD : UpDownBase&lt;DateTime&gt;"/>
            <StackPanel x:Name="spTUD" Grid.Row="1" Grid.Column="1" Margin="5"/>
            <TextBlock Grid.Row="0" Grid.Column="2" Style="{StaticResource Description}" Text="SUD : UpDownBase&lt;string&gt;"/>
            <StackPanel x:Name="spSUD" Grid.Row="1" Grid.Column="2" Margin="5"/>
        </Grid>

        <!-- Interactive Usage -->
        <ContentControl Content="Interactive Usage" Style="{StaticResource Header}" />
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="200" />
                <ColumnDefinition Width="10" />
                <ColumnDefinition Width="300" />
            </Grid.ColumnDefinitions>
            <Grid>
                <StackPanel x:Name="sp">
                    <!--
                    <TextBlock x:Name="output" />
                    -->
                </StackPanel>
            </Grid>
            <Grid Grid.Column="2">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="80" />
                    <ColumnDefinition Width="5" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>

                <TextBlock Text="Type:" Grid.Row="0" Grid.Column="0" />
                <ListBox x:Name="lbType" Grid.Row="0" Grid.Column="2" HorizontalAlignment="Left">
                    <ListBoxItem Content="NUD : UpDownBase&lt;int&gt;" IsSelected="True"/>
                    <ListBoxItem Content="TUD : UpDownBase&lt;DateTime&gt;" />
                    <ListBoxItem Content="SUD : UpDownBase&lt;string&gt;" />
                </ListBox>

                <TextBlock Text="Value:" Grid.Row="1" Grid.Column="0" />
                <TextBox x:Name="tbValue" Grid.Row="1" Grid.Column="2" />
<!--
                <TextBlock Text="SpinnerStyle:" Grid.Row="2" Grid.Column="0" />
                <TextBox x:Name="tbSpinnerStyle" Grid.Row="2" Grid.Column="2" />

                <CheckBox x:Name="cbIsCyclic" Grid.Row="3" Grid.Column="2" 
                          IsChecked="False"
                          HorizontalAlignment="Left" Content="IsCyclic"/>
-->

                <CheckBox x:Name="cbIsEditable" Grid.Row="4" Grid.Column="2" 
                          IsChecked="True"
                          HorizontalAlignment="Left" Content="IsEditable"/>

                <CheckBox x:Name="cbIsEnabled" Grid.Row="5" Grid.Column="2"
                          IsChecked="True"
                          HorizontalAlignment="Left" Content="IsEnabled" />

                <Button x:Name="btnChange" Grid.Row="6" Grid.Column="2"
                        HorizontalAlignment="Left" Content="Change!"/>
            </Grid>
        </Grid>
        <src:SourceViewer xmlns:src="clr-namespace:System.Windows.Controls.Samples;assembly=System.Windows.Controls.Samples.Common" xmlns:sys="clr-namespace:System;assembly=mscorlib">
  <src:SourceFile Path="UpDownBaseSample.xaml">
    <src:SourceFile.Source>
      <sys:String>&lt;!--
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
--&gt;

&lt;UserControl x:Class="System.Windows.Controls.Samples.UpDownBaseSample"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    
    xmlns:samples="clr-namespace:System.Windows.Controls.Samples"&gt;
    &lt;StackPanel&gt;
        &lt;!-- UpDownBase&amp;lt;T&amp;gt; --&gt;
        &lt;ContentControl Content="UpDownBase&amp;lt;T&amp;gt;" Style="{StaticResource Header}" /&gt;
        &lt;Grid&gt;
            &lt;Grid.RowDefinitions&gt;
                &lt;RowDefinition Height="Auto" /&gt;
                &lt;RowDefinition Height="50" /&gt;
            &lt;/Grid.RowDefinitions&gt;
            &lt;Grid.ColumnDefinitions&gt;
                &lt;ColumnDefinition Width="200" /&gt;
                &lt;ColumnDefinition Width="200" /&gt;
                &lt;ColumnDefinition Width="200" /&gt;
            &lt;/Grid.ColumnDefinitions&gt;

            &lt;TextBlock Grid.Row="0" Grid.Column="0" Style="{StaticResource Description}" Text="NUD : UpDownBase&amp;lt;int&amp;gt;"/&gt;
            &lt;StackPanel x:Name="spNUD" Grid.Row="1" Grid.Column="0" Margin="5"/&gt;
            &lt;TextBlock Grid.Row="0" Grid.Column="1" Style="{StaticResource Description}" Text="TUD : UpDownBase&amp;lt;DateTime&amp;gt;"/&gt;
            &lt;StackPanel x:Name="spTUD" Grid.Row="1" Grid.Column="1" Margin="5"/&gt;
            &lt;TextBlock Grid.Row="0" Grid.Column="2" Style="{StaticResource Description}" Text="SUD : UpDownBase&amp;lt;string&amp;gt;"/&gt;
            &lt;StackPanel x:Name="spSUD" Grid.Row="1" Grid.Column="2" Margin="5"/&gt;
        &lt;/Grid&gt;

        &lt;!-- Interactive Usage --&gt;
        &lt;ContentControl Content="Interactive Usage" Style="{StaticResource Header}" /&gt;
        &lt;Grid&gt;
            &lt;Grid.ColumnDefinitions&gt;
                &lt;ColumnDefinition Width="200" /&gt;
                &lt;ColumnDefinition Width="10" /&gt;
                &lt;ColumnDefinition Width="300" /&gt;
            &lt;/Grid.ColumnDefinitions&gt;
            &lt;Grid&gt;
                &lt;StackPanel x:Name="sp"&gt;
                    &lt;!--
                    &lt;TextBlock x:Name="output" /&gt;
                    --&gt;
                &lt;/StackPanel&gt;
            &lt;/Grid&gt;
            &lt;Grid Grid.Column="2"&gt;
                &lt;Grid.ColumnDefinitions&gt;
                    &lt;ColumnDefinition Width="80" /&gt;
                    &lt;ColumnDefinition Width="5" /&gt;
                    &lt;ColumnDefinition Width="*" /&gt;
                &lt;/Grid.ColumnDefinitions&gt;
                &lt;Grid.RowDefinitions&gt;
                    &lt;RowDefinition Height="Auto" /&gt;
                    &lt;RowDefinition Height="Auto" /&gt;
                    &lt;RowDefinition Height="Auto" /&gt;
                    &lt;RowDefinition Height="Auto" /&gt;
                    &lt;RowDefinition Height="Auto" /&gt;
                    &lt;RowDefinition Height="Auto" /&gt;
                    &lt;RowDefinition Height="Auto" /&gt;
                    &lt;RowDefinition Height="Auto" /&gt;
                &lt;/Grid.RowDefinitions&gt;

                &lt;TextBlock Text="Type:" Grid.Row="0" Grid.Column="0" /&gt;
                &lt;ListBox x:Name="lbType" Grid.Row="0" Grid.Column="2" HorizontalAlignment="Left"&gt;
                    &lt;ListBoxItem Content="NUD : UpDownBase&amp;lt;int&amp;gt;" IsSelected="True"/&gt;
                    &lt;ListBoxItem Content="TUD : UpDownBase&amp;lt;DateTime&amp;gt;" /&gt;
                    &lt;ListBoxItem Content="SUD : UpDownBase&amp;lt;string&amp;gt;" /&gt;
                &lt;/ListBox&gt;

                &lt;TextBlock Text="Value:" Grid.Row="1" Grid.Column="0" /&gt;
                &lt;TextBox x:Name="tbValue" Grid.Row="1" Grid.Column="2" /&gt;
&lt;!--
                &lt;TextBlock Text="SpinnerStyle:" Grid.Row="2" Grid.Column="0" /&gt;
                &lt;TextBox x:Name="tbSpinnerStyle" Grid.Row="2" Grid.Column="2" /&gt;

                &lt;CheckBox x:Name="cbIsCyclic" Grid.Row="3" Grid.Column="2" 
                          IsChecked="False"
                          HorizontalAlignment="Left" Content="IsCyclic"/&gt;
--&gt;

                &lt;CheckBox x:Name="cbIsEditable" Grid.Row="4" Grid.Column="2" 
                          IsChecked="True"
                          HorizontalAlignment="Left" Content="IsEditable"/&gt;

                &lt;CheckBox x:Name="cbIsEnabled" Grid.Row="5" Grid.Column="2"
                          IsChecked="True"
                          HorizontalAlignment="Left" Content="IsEnabled" /&gt;

                &lt;Button x:Name="btnChange" Grid.Row="6" Grid.Column="2"
                        HorizontalAlignment="Left" Content="Change!"/&gt;
            &lt;/Grid&gt;
        &lt;/Grid&gt;
    &lt;/StackPanel&gt;
&lt;/UserControl&gt;
</sys:String>
    </src:SourceFile.Source>
  </src:SourceFile>
  <src:SourceFile Path="UpDownBaseSample.xaml.cs">
    <src:SourceFile.Source>
      <sys:String>// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.

using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;

[assembly: SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Scope = "member", Target = "System.Windows.Controls.Samples.UpDownBaseSample+SUD.#.ctor()")]
[assembly: SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Scope = "member", Target = "System.Windows.Controls.Samples.UpDownBaseSample+TUD.#.ctor()")]
[assembly: SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Scope = "member", Target = "System.Windows.Controls.Samples.UpDownBaseSample+NUD.#.ctor()")]

namespace System.Windows.Controls.Samples
{
    /// &lt;summary&gt;
    /// UpDownBase sample page.
    /// &lt;/summary&gt;
    [Sample("UpDownBase", DifficultyLevel.Basic)]
    [Category("UpDownBase")]
    public partial class UpDownBaseSample : UserControl
    {
        /// &lt;summary&gt;
        /// Initializes a new instance of the UpDownBaseSample class.
        /// &lt;/summary&gt;
        public UpDownBaseSample()
        {
            InitializeComponent();

            // create instance of the test non generic sub classes
            spNUD.Children.Add(new NUD());
            spTUD.Children.Add(new TUD());
            spSUD.Children.Add(new SUD());

            btnChange.Click += (s, a) =&gt; CreateUDB();
        }

        /// &lt;summary&gt;
        /// This function does following three things:
        /// 1. Remove existing interactive UpDownBase control if it exists;
        /// 2. Create a new instance of selected UpDownBase subclass type;
        /// 3. Add the newly created UpDownBase control to visual tree.
        /// &lt;/summary&gt;
        private void CreateUDB()
        {
            if (udb != null)
            {
                Debug.Assert(udb == sp.Children[0], "udb should be sp's only child!");
                sp.Children.Remove(udb);
            }

            switch (lbType.SelectedIndex)
            {
                case 0:
                    udb = new NUD();
                    ConfigUDB((UpDownBase&lt;int&gt;)udb);
                    break;
                case 1:
                    udb = new TUD();
                    ConfigUDB((UpDownBase&lt;DateTime&gt;)udb);
                    break;
                case 2:
                    udb = new SUD();
                    ConfigUDB((UpDownBase&lt;string&gt;)udb);
                    break;
            }

            sp.Children.Add(udb);
        }

        /// &lt;summary&gt;
        /// Configure a UpDownBase&amp;lt;T&amp;gt; control.
        /// &lt;/summary&gt;
        /// &lt;typeparam name="T"&gt;Type parameter.&lt;/typeparam&gt;
        /// &lt;param name="udbt"&gt;UpDownBase&amp;lt;T&amp;gt; control.&lt;/param&gt;
        private void ConfigUDB&lt;T&gt;(UpDownBase&lt;T&gt; udbt)
        {
            Debug.Assert(udbt != null, "udb should not be null!");

            udbt.Value = ParseUtility.ReadValue(tbValue, udbt.Value);
            ////udbt.IsCyclic = (bool)cbIsCyclic.IsChecked;
            udbt.IsEditable = (bool)cbIsEditable.IsChecked;
            udbt.IsEnabled = (bool)cbIsEnabled.IsChecked;
        }

        /// &lt;summary&gt;
        /// The interactive UpDownBase control.
        /// &lt;/summary&gt;
        private UpDownBase udb;

        #region Non-generic test classes inheriting from UpDownBase&lt;T&gt;
        /// &lt;summary&gt;
        /// Non-generic test class inheriting from UpDownBase&amp;lt;int&amp;gt;.
        /// &lt;/summary&gt;
        /// &lt;remarks&gt;
        /// Value is of type int, in between 0 and 10.
        /// IsCyclic decides whether Value will wrap around 0 and 10.
        /// OnIncrement and OnDecrement change Value by 1.
        /// &lt;/remarks&gt;
        [TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
        [TemplateVisualState(Name = "MouseOver", GroupName = "CommonStates")]
        [TemplateVisualState(Name = "Pressed", GroupName = "CommonStates")]
        [TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]

        [TemplateVisualState(Name = "Focused", GroupName = "FocusStates")]
        [TemplateVisualState(Name = "Unfocused", GroupName = "FocusStates")]

        [TemplatePart(Name = "TextName", Type = typeof(TextBox))]
        [TemplatePart(Name = "SpinnerName", Type = typeof(Spinner))]
        [StyleTypedProperty(Property = "SpinnerStyle", StyleTargetType = typeof(Spinner))]
        internal class NUD : UpDownBase&lt;int&gt;
        {
            /// &lt;summary&gt;
            /// Private variable to replace IsCyclic property for now removed from UpDownBase&amp;lt;T&amp;gt;.
            /// &lt;/summary&gt;
            private bool IsCyclic = true;

            /// &lt;summary&gt;
            /// Internal constructor.
            /// &lt;/summary&gt;
            internal NUD()
                : base()
            {
                Value = 0;
            }

            /// &lt;summary&gt;
            /// Called by OnSpin when the spin direction is SpinDirection.Increase.
            /// &lt;/summary&gt;
            protected override void OnIncrement()
            {
                Value = IsCyclic ? (Value + 1) % 10 : Math.Min(10, Value + 1);
            }

            /// &lt;summary&gt;
            /// Called by OnSpin when the spin direction is SpinDirection.Increase.
            /// &lt;/summary&gt;
            protected override void OnDecrement()
            {
                Value = IsCyclic ? (Value - 1) % 10 : Math.Max(0, Value - 1);
            }

            /// &lt;summary&gt;
            /// Called by ApplyValue to parse user input.
            /// &lt;/summary&gt;
            /// &lt;param name="text"&gt;User input.&lt;/param&gt;
            /// &lt;returns&gt;Value parsed from user input.&lt;/returns&gt;
            protected override int ParseValue(string text)
            {
                return int.Parse(text, CultureInfo.CurrentCulture);
            }

            /// &lt;summary&gt;
            /// Called to render Value for Text template part to display.
            /// &lt;/summary&gt;
            /// &lt;returns&gt;Formatted Value.&lt;/returns&gt;
            protected override string FormatValue()
            {
                return Value.ToString(CultureInfo.CurrentCulture);
            }
        }

        /// &lt;summary&gt;
        /// Non-generic test class inheriting from UpDownBase&amp;lt;DateTime&amp;gt;.
        /// &lt;/summary&gt;
        /// &lt;remarks&gt;
        /// Value is of type DateTime. 
        /// IsCyclic decides whether Value will wrap around DateTime.MinValue and DateTime.MaxValue.
        /// OnIncrement and OnDecrement change Value by one hour.
        /// &lt;/remarks&gt;
        [TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
        [TemplateVisualState(Name = "MouseOver", GroupName = "CommonStates")]
        [TemplateVisualState(Name = "Pressed", GroupName = "CommonStates")]
        [TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]

        [TemplateVisualState(Name = "Focused", GroupName = "FocusStates")]
        [TemplateVisualState(Name = "Unfocused", GroupName = "FocusStates")]

        [TemplatePart(Name = "TextName", Type = typeof(TextBox))]
        [TemplatePart(Name = "SpinnerName", Type = typeof(Spinner))]
        [StyleTypedProperty(Property = "SpinnerStyle", StyleTargetType = typeof(Spinner))]
        internal class TUD : UpDownBase&lt;DateTime&gt;
        {
            /// &lt;summary&gt;
            /// Private variable to replace IsCyclic property for now removed from UpDownBase&amp;lt;T&amp;gt;.
            /// &lt;/summary&gt;
            private bool IsCyclic = true;

            /// &lt;summary&gt;
            /// Internal constructor.
            /// &lt;/summary&gt;
            internal TUD()
                : base()
            {
                Value = DateTime.Now;
            }

            /// &lt;summary&gt;
            /// Called by OnSpin when the spin direction is SpinDirection.Increase.
            /// &lt;/summary&gt;
            protected override void OnIncrement()
            {
                try
                {
                    Value = Value.AddHours(1);
                }
                catch (ArgumentOutOfRangeException)
                {
                    Value = IsCyclic ? DateTime.MinValue : DateTime.MaxValue;
                }
            }

            /// &lt;summary&gt;
            /// Called by OnSpin when the spin direction is SpinDirection.Increase.
            /// &lt;/summary&gt;
            protected override void OnDecrement()
            {
                try
                {
                    Value = Value.AddHours(-1);
                }
                catch (ArgumentOutOfRangeException)
                {
                    Value = IsCyclic ? DateTime.MaxValue : DateTime.MinValue;
                }
            }

            /// &lt;summary&gt;
            /// Called by ApplyValue to parse user input.
            /// &lt;/summary&gt;
            /// &lt;param name="text"&gt;User input.&lt;/param&gt;
            /// &lt;returns&gt;Value parsed from user input.&lt;/returns&gt;
            protected override DateTime ParseValue(string text)
            {
                return DateTime.Parse(text, CultureInfo.CurrentCulture);
            }

            /// &lt;summary&gt;
            /// Called to render Value for Text template part to display.
            /// &lt;/summary&gt;
            /// &lt;returns&gt;Formatted Value.&lt;/returns&gt;
            protected override string FormatValue()
            {
                return Value.ToShortTimeString();
            }
        }

        /// &lt;summary&gt;
        /// Non-generic class for UpDownBase&amp;lt;T&amp;gt; testing only.
        /// &lt;/summary&gt;
        /// &lt;remarks&gt;
        /// Value is of type string.
        /// OnIncrement and OnDecrement change string length by 1 character.
        /// IsCyclic decides whether Value length will cycle through 0 to 10.
        /// &lt;/remarks&gt;
        [TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
        [TemplateVisualState(Name = "MouseOver", GroupName = "CommonStates")]
        [TemplateVisualState(Name = "Pressed", GroupName = "CommonStates")]
        [TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]

        [TemplateVisualState(Name = "Focused", GroupName = "FocusStates")]
        [TemplateVisualState(Name = "Unfocused", GroupName = "FocusStates")]

        [TemplatePart(Name = "TextName", Type = typeof(TextBox))]
        [TemplatePart(Name = "SpinnerName", Type = typeof(Spinner))]
        [StyleTypedProperty(Property = "SpinnerStyle", StyleTargetType = typeof(Spinner))]
        internal class SUD : UpDownBase&lt;string&gt;
        {
            /// &lt;summary&gt;
            /// Private variable to replace IsCyclic property for now removed from UpDownBase&amp;lt;T&amp;gt;.
            /// &lt;/summary&gt;
            private bool IsCyclic = true;

            /// &lt;summary&gt;
            /// Internal constructor.
            /// &lt;/summary&gt;
            internal SUD()
                : base()
            {
                Value = "0";
            }

            /// &lt;summary&gt;
            /// Called by OnSpin when the spin direction is SpinDirection.Increase.
            /// &lt;/summary&gt;
            protected override void OnIncrement()
            {
                string value = string.IsNullOrEmpty(Value) ? "0" : Value;
                if (value.Length &gt;= 10)
                {
                    if (IsCyclic)
                    {
                        value = "0";
                    }
                }
                else
                {
                    value = value + value.Length.ToString(CultureInfo.CurrentCulture);
                }
                Value = value;
            }

            /// &lt;summary&gt;
            /// Called by OnSpin when the spin direction is SpinDirection.Increase.
            /// &lt;/summary&gt;
            protected override void OnDecrement()
            {
                string value = string.IsNullOrEmpty(Value) ? "0" : Value;
                if (value.Length &lt;= 1)
                {
                    if (IsCyclic)
                    {
                        value = "0123456789";
                    }
                }
                else
                {
                    value = value.Substring(0, value.Length - 1);
                }
                Value = value;
            }

            /// &lt;summary&gt;
            /// Called by ApplyValue to parse user input.
            /// &lt;/summary&gt;
            /// &lt;param name="text"&gt;User input.&lt;/param&gt;
            /// &lt;returns&gt;Value parsed from user input.&lt;/returns&gt;
            protected override string ParseValue(string text)
            {
                if (string.IsNullOrEmpty(text))
                {
                    text = "0";
                }

                if (text.Length &gt; 10)
                {
                    text = text.Substring(0, 10);
                }

                return text;
            }

            /// &lt;summary&gt;
            /// Called to render Value for Text template part to display.
            /// &lt;/summary&gt;
            /// &lt;returns&gt;Formatted Value.&lt;/returns&gt;
            protected override string FormatValue()
            {
                return string.IsNullOrEmpty(Value) ? "0" : Value;
            }
        }
        #endregion 
    }
}
</sys:String>
    </src:SourceFile.Source>
  </src:SourceFile>
  <src:SourceFile Path="UpDownBaseSample.xaml.vb">
    <src:SourceFile.Source>
      <sys:String>' (c) Copyright Microsoft Corporation.
' This source is subject to the Microsoft Public License (Ms-PL).
' Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
' All other rights reserved.

Imports Microsoft.VisualBasic
Imports System
Imports System.Diagnostics
Imports System.Diagnostics.CodeAnalysis
Imports System.Globalization
Imports System.Windows
Imports System.Windows.Controls
Imports System.ComponentModel

&lt;Assembly: SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Scope:="member", Target:="System.Windows.Controls.Samples.UpDownBaseSample+SUD.#.ctor()")&gt; 
&lt;Assembly: SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Scope:="member", Target:="System.Windows.Controls.Samples.UpDownBaseSample+TUD.#.ctor()")&gt; 
&lt;Assembly: SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Scope:="member", Target:="System.Windows.Controls.Samples.UpDownBaseSample+NUD.#.ctor()")&gt; 

''' &lt;summary&gt;
''' UpDownBase sample page.
''' &lt;/summary&gt;
&lt;Sample("UpDownBase", DifficultyLevel.Basic), Category("UpDownBase")&gt; _
Partial Public Class UpDownBaseSample
    Inherits UserControl
    ''' &lt;summary&gt;
    ''' Initializes a new instance of the UpDownBaseSample class.
    ''' &lt;/summary&gt;
    &lt;System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Justification:="InitializeComponent Required by Visual Studio.")&gt; _
    Public Sub New()
        InitializeComponent()

        ' create instance of the test non generic sub classes
        spNUD.Children.Add(New NUD())
        spTUD.Children.Add(New TUD())
        spSUD.Children.Add(New SUD())
    End Sub

    ''' &lt;summary&gt;
    ''' This function does following three things:
    ''' 1. Remove existing interactive UpDownBase control if it exists;
    ''' 2. Create a new instance of selected UpDownBase subclass type;
    ''' 3. Add the newly created UpDownBase control to visual tree.
    ''' &lt;/summary&gt;
    ''' &lt;param name="sender"&gt;The sender.&lt;/param&gt;
    ''' &lt;param name="e"&gt;The event arguments.&lt;/param&gt;
    Private Sub CreateUDB(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles btnChange.Click
        If udb IsNot Nothing Then
            Debug.Assert(udb Is sp.Children(0), "udb should be sp's only child!")
            sp.Children.Remove(udb)
        End If

        Select Case lbType.SelectedIndex
            Case 0
                udb = New NUD()
                ConfigUDB(CType(udb, UpDownBase(Of Integer)))
            Case 1
                udb = New TUD()
                ConfigUDB(CType(udb, UpDownBase(Of DateTime)))
            Case 2
                udb = New SUD()
                ConfigUDB(CType(udb, UpDownBase(Of String)))
        End Select

        sp.Children.Add(udb)
    End Sub

    ''' &lt;summary&gt;
    ''' Configure a UpDownBase&amp;lt;T&amp;gt; control.
    ''' &lt;/summary&gt;
    ''' &lt;typeparam name="T"&gt;Type parameter.&lt;/typeparam&gt;
    ''' &lt;param name="udbt"&gt;UpDownBase&amp;lt;T&amp;gt; control.&lt;/param&gt;
    Private Sub ConfigUDB(Of T)(ByVal udbt As UpDownBase(Of T))
        Debug.Assert(udbt IsNot Nothing, "udb should not be null!")

        udbt.Value = ParseUtility.ReadValue(tbValue, udbt.Value)
        ' udbt.IsCyclic = (bool)cbIsCyclic.IsChecked;
        udbt.IsEditable = CBool(cbIsEditable.IsChecked)
        udbt.IsEnabled = CBool(cbIsEnabled.IsChecked)
    End Sub

    ''' &lt;summary&gt;
    ''' The interactive UpDownBase control.
    ''' &lt;/summary&gt;
    Private udb As UpDownBase

#Region "Non-generic test classes inheriting from UpDownBase&lt;T&gt;"
    ''' &lt;summary&gt;
    ''' Non-generic test class inheriting from UpDownBase&amp;lt;int&amp;gt;.
    ''' &lt;/summary&gt;
    ''' &lt;remarks&gt;
    ''' Value is of type int, in between 0 and 10.
    ''' IsCyclic decides whether Value will wrap around 0 and 10.
    ''' OnIncrement and OnDecrement change Value by 1.
    ''' &lt;/remarks&gt;
    &lt;TemplateVisualState(Name:="Normal", GroupName:="CommonStates"), _
    TemplateVisualState(Name:="MouseOver", GroupName:="CommonStates"), _
    TemplateVisualState(Name:="Pressed", GroupName:="CommonStates"), _
    TemplateVisualState(Name:="Disabled", GroupName:="CommonStates"), _
    TemplateVisualState(Name:="Focused", GroupName:="FocusStates"), _
    TemplateVisualState(Name:="Unfocused", GroupName:="FocusStates"), _
    TemplatePart(Name:="TextName", Type:=GetType(TextBox)), _
    TemplatePart(Name:="SpinnerName", Type:=GetType(Spinner)), _
    StyleTypedProperty(Property:="SpinnerStyle", StyleTargetType:=GetType(Spinner))&gt; _
    Friend Class NUD
        Inherits UpDownBase(Of Integer)
        ''' &lt;summary&gt;
        ''' Private variable to replace IsCyclic property for now removed from UpDownBase&amp;lt;T&amp;gt;.
        ''' &lt;/summary&gt;
        Private IsCyclic As Boolean = True

        ''' &lt;summary&gt;
        ''' Internal constructor.
        ''' &lt;/summary&gt;
        Friend Sub New()
            MyBase.New()
            Value = 0
        End Sub

        ''' &lt;summary&gt;
        ''' Called by OnSpin when the spin direction is SpinDirection.Increase.
        ''' &lt;/summary&gt;
        Protected Overrides Sub OnIncrement()
            Value = If(IsCyclic, (Value + 1) Mod 10, Math.Min(10, Value + 1))
        End Sub

        ''' &lt;summary&gt;
        ''' Called by OnSpin when the spin direction is SpinDirection.Increase.
        ''' &lt;/summary&gt;
        Protected Overrides Sub OnDecrement()
            Value = If(IsCyclic, (Value - 1) Mod 10, Math.Max(0, Value - 1))
        End Sub

        ''' &lt;summary&gt;
        ''' Called by ApplyValue to parse user input.
        ''' &lt;/summary&gt;
        ''' &lt;param name="text"&gt;User input.&lt;/param&gt;
        ''' &lt;returns&gt;Value parsed from user input.&lt;/returns&gt;
        Protected Overrides Function ParseValue(ByVal text As String) As Integer
            Return Integer.Parse(text, CultureInfo.CurrentCulture)
        End Function

        ''' &lt;summary&gt;
        ''' Called to render Value for Text template part to display.
        ''' &lt;/summary&gt;
        ''' &lt;returns&gt;Formatted Value.&lt;/returns&gt;
        Protected Overrides Function FormatValue() As String
            Return Value.ToString(CultureInfo.CurrentCulture)
        End Function
    End Class

    ''' &lt;summary&gt;
    ''' Non-generic test class inheriting from UpDownBase&amp;lt;DateTime&amp;gt;.
    ''' &lt;/summary&gt;
    ''' &lt;remarks&gt;
    ''' Value is of type DateTime. 
    ''' IsCyclic decides whether Value will wrap around DateTime.MinValue and DateTime.MaxValue.
    ''' OnIncrement and OnDecrement change Value by one hour.
    ''' &lt;/remarks&gt;
    &lt;TemplateVisualState(Name:="Normal", GroupName:="CommonStates"), _
    TemplateVisualState(Name:="MouseOver", GroupName:="CommonStates"), _
    TemplateVisualState(Name:="Pressed", GroupName:="CommonStates"), _
    TemplateVisualState(Name:="Disabled", GroupName:="CommonStates"), _
    TemplateVisualState(Name:="Focused", GroupName:="FocusStates"), _
    TemplateVisualState(Name:="Unfocused", GroupName:="FocusStates"), _
    TemplatePart(Name:="TextName", Type:=GetType(TextBox)), _
    TemplatePart(Name:="SpinnerName", Type:=GetType(Spinner)), _
    StyleTypedProperty(Property:="SpinnerStyle", StyleTargetType:=GetType(Spinner))&gt; _
    Friend Class TUD
        Inherits UpDownBase(Of DateTime)
        ''' &lt;summary&gt;
        ''' Private variable to replace IsCyclic property for now removed from UpDownBase&amp;lt;T&amp;gt;.
        ''' &lt;/summary&gt;
        Private IsCyclic As Boolean = True

        ''' &lt;summary&gt;
        ''' Internal constructor.
        ''' &lt;/summary&gt;
        Friend Sub New()
            MyBase.New()
            Value = DateTime.Now
        End Sub

        ''' &lt;summary&gt;
        ''' Called by OnSpin when the spin direction is SpinDirection.Increase.
        ''' &lt;/summary&gt;
        Protected Overrides Sub OnIncrement()
            Try
                Value = Value.AddHours(1)
            Catch e1 As ArgumentOutOfRangeException
                Value = If(IsCyclic, DateTime.MinValue, DateTime.MaxValue)
            End Try
        End Sub

        ''' &lt;summary&gt;
        ''' Called by OnSpin when the spin direction is SpinDirection.Increase.
        ''' &lt;/summary&gt;
        Protected Overrides Sub OnDecrement()
            Try
                Value = Value.AddHours(-1)
            Catch e1 As ArgumentOutOfRangeException
                Value = If(IsCyclic, DateTime.MaxValue, DateTime.MinValue)
            End Try
        End Sub

        ''' &lt;summary&gt;
        ''' Called by ApplyValue to parse user input.
        ''' &lt;/summary&gt;
        ''' &lt;param name="text"&gt;User input.&lt;/param&gt;
        ''' &lt;returns&gt;Value parsed from user input.&lt;/returns&gt;
        Protected Overrides Function ParseValue(ByVal text As String) As DateTime
            Return DateTime.Parse(text, CultureInfo.CurrentCulture)
        End Function

        ''' &lt;summary&gt;
        ''' Called to render Value for Text template part to display.
        ''' &lt;/summary&gt;
        ''' &lt;returns&gt;Formatted Value.&lt;/returns&gt;
        Protected Overrides Function FormatValue() As String
            Return Value.ToShortTimeString()
        End Function
    End Class

    ''' &lt;summary&gt;
    ''' Non-generic class for UpDownBase&amp;lt;T&amp;gt; testing only.
    ''' &lt;/summary&gt;
    ''' &lt;remarks&gt;
    ''' Value is of type string.
    ''' OnIncrement and OnDecrement change string length by 1 character.
    ''' IsCyclic decides whether Value length will cycle through 0 to 10.
    ''' &lt;/remarks&gt;
    &lt;TemplateVisualState(Name:="Normal", GroupName:="CommonStates"), _
    TemplateVisualState(Name:="MouseOver", GroupName:="CommonStates"), _
    TemplateVisualState(Name:="Pressed", GroupName:="CommonStates"), _
    TemplateVisualState(Name:="Disabled", GroupName:="CommonStates"), _
    TemplateVisualState(Name:="Focused", GroupName:="FocusStates"), _
    TemplateVisualState(Name:="Unfocused", GroupName:="FocusStates"), _
    TemplatePart(Name:="TextName", Type:=GetType(TextBox)), _
    TemplatePart(Name:="SpinnerName", Type:=GetType(Spinner)), _
    StyleTypedProperty(Property:="SpinnerStyle", StyleTargetType:=GetType(Spinner))&gt; _
    Friend Class SUD
        Inherits UpDownBase(Of String)
        ''' &lt;summary&gt;
        ''' Private variable to replace IsCyclic property for now removed from UpDownBase&amp;lt;T&amp;gt;.
        ''' &lt;/summary&gt;
        Private IsCyclic As Boolean = True

        ''' &lt;summary&gt;
        ''' Internal constructor.
        ''' &lt;/summary&gt;
        Friend Sub New()
            MyBase.New()
            Me.Value = "0"
        End Sub

        ''' &lt;summary&gt;
        ''' Called by OnSpin when the spin direction is SpinDirection.Increase.
        ''' &lt;/summary&gt;
        Protected Overrides Sub OnIncrement()
            Dim value As String = If(String.IsNullOrEmpty(Me.Value), "0", Me.Value)
            If value.Length &gt;= 10 Then
                If IsCyclic Then
                    value = "0"
                End If
            Else
                value = value &amp; value.Length.ToString(CultureInfo.CurrentCulture)
            End If
            Me.Value = value
        End Sub

        ''' &lt;summary&gt;
        ''' Called by OnSpin when the spin direction is SpinDirection.Increase.
        ''' &lt;/summary&gt;
        Protected Overrides Sub OnDecrement()
            Dim value As String = If(String.IsNullOrEmpty(Me.Value), "0", Me.Value)
            If value.Length &lt;= 1 Then
                If IsCyclic Then
                    value = "0123456789"
                End If
            Else
                value = value.Substring(0, value.Length - 1)
            End If
            Me.Value = value
        End Sub

        ''' &lt;summary&gt;
        ''' Called by ApplyValue to parse user input.
        ''' &lt;/summary&gt;
        ''' &lt;param name="text"&gt;User input.&lt;/param&gt;
        ''' &lt;returns&gt;Value parsed from user input.&lt;/returns&gt;
        Protected Overrides Function ParseValue(ByVal text As String) As String
            If String.IsNullOrEmpty(text) Then
                text = "0"
            End If

            If text.Length &gt; 10 Then
                text = text.Substring(0, 10)
            End If

            Return text
        End Function

        ''' &lt;summary&gt;
        ''' Called to render Value for Text template part to display.
        ''' &lt;/summary&gt;
        ''' &lt;returns&gt;Formatted Value.&lt;/returns&gt;
        Protected Overrides Function FormatValue() As String
            Return If(String.IsNullOrEmpty(Value), "0", Value)
        End Function
    End Class
#End Region
End Class</sys:String>
    </src:SourceFile.Source>
  </src:SourceFile>
</src:SourceViewer>
    </StackPanel>
</UserControl>
